import { Commit, createStore } from 'vuex'
import axios, { AxiosRequestConfig } from 'axios'
import { arrToObj, objToArr } from './helper'
export interface ResponseType<P = {}> {
  code: number,
  msg: string,
  data: P
}
export interface ImageProps {
  _id?: string,
  url?: string,
  createdAt?: string
}

interface ListProps<P>{
[id:string]:P
}

export interface UserProps {
  isLogin: boolean;
  nickName?: string;
  _id?: string;
  column?: string,
  email?: string,
  avatar?: ImageProps;
  description?: string;
}
export interface PostProps {
  _id?: string;
  title: string;
  excerpt?: string;
  content?: string;
  image?: ImageProps | string;
  createdAt?: string;
  column: string;
  author?: string | UserProps;
  isHTML?: boolean;
}
export interface ColumnProps {
  _id: string,
  title: string,
  avatar?: ImageProps,
  description: string,
  image?: ImageProps,
}
// 错误提示接口规范
export interface GlobalErrorProps {
  status: boolean,
  message?: string
}
export interface Colomn{
  data:ListProps<ColumnProps>,
  isLoaded:boolean
}

export interface GlobalDataProps {
  error: GlobalErrorProps,
  token: string,
  isLoading: boolean,
  columns:{data:ListProps<ColumnProps>;currentPage:number, isLoaded: boolean, total:number;};
  posts: {data:ListProps<PostProps>;loadedColumn: string[] };
  user: UserProps;
}

// get
const getAndCommit = async (url: string, mutationName: string, commit: Commit) => {
  const { data } = await axios.get(url)
  commit(mutationName, data)
  return data
}
// post
const postAndCommit = async (url: string, mutationName: string, commit: Commit, payLoad: any) => {
  const { data } = await axios.post(url, payLoad)
  commit(mutationName, data)
  return data
}

const asyncAndCommit = async (url: string, mutationName: string, commit: Commit,
   config: AxiosRequestConfig = { method: 'get' }, extraData?:any) => {
  const { data } = await axios(url, config)
  if (extraData) {
    commit(mutationName, { data, extraData })
  } else {
    commit(mutationName, data)
  }
  return data// (返回的是一个promise)
}
const store = createStore<GlobalDataProps>({
  state: {
    error: { status: false },
    token: localStorage.getItem('token') || '',
    isLoading: false,
    columns: { data: {}, currentPage: 0, isLoaded: false, total: 0 },
    posts: { data: {}, loadedColumn: [] },
    user: { isLogin: false }
  },
  // 同步请求
  mutations: {
    // login(state) {
    //   state.user = { ...state.user, isLogin: true, name: '雪宝', columnId: 1 }
    // },
    cratePost(state, newPost) {
      //  state.posts 是一个对象
      state.posts.data[newPost.id] = newPost
      // state.posts.push(newPost)
    },
    fetchColumns(state, rawData) {
      const { list, count, currentPage } = rawData.data
      const { data } = state.columns

      state.columns = {
        data: { ...data, ...arrToObj(list) },
        isLoaded: true,
        total: count,
        currentPage: currentPage * 1
      }
      // state.columns.data = arrToObj(rawData.data.list)
      // state.columns.isLoaded = true
    },
    fetchColumn(state, rawData) {
      state.columns.data[rawData.data._id] = rawData.data// 对象
    },
    fetchPosts(state, { data: rawData, extraData: columnId }) {
      state.posts.data = { ...state.posts.data, ...arrToObj(rawData.data.list) }
      state.posts.loadedColumn.push(columnId)
    },
    setLoading(state, status) {
      state.isLoading = status
    },
    setError(state, e: GlobalErrorProps) {
      state.error = e
    },
    fetchCurrentUser(state, rawData) {
      state.user = { isLogin: true, ...rawData.data }
    },

    login(state, rawData) {
      const { token } = rawData.data

      localStorage.setItem('token', token)// 登陆成功之后设置token
      state.token = token
      axios.defaults.headers.common.Authorization = `Bearer ${token}`
    },
    // 退出登陆
    logout(state) {
      state.token = ''
      state.user = { isLogin: false }
      localStorage.removeItem('token')
      delete axios.defaults.headers.common.Authorization
    },
    fetchPost(state, rawData) {
      state.posts.data[rawData.data._id] = rawData.data
    },
    updatePost(state, { data }) {
      // 找到他进行一个更新
      // state.posts = state.posts.map(post => {
      //   if (post._id === data._id) {
      //     return data
      //   } else {
      //     return post
      //   }
      // })
      state.posts.data[data._id] = data
    },
    deletePost(state, { data }) {
      // state.posts = state.posts.filter(post => post._id !== data._id)
      delete state.posts.data[data._id]
    }
  },
  // 异步请求
  actions: {
    fetchColumns(context, params = {}) {
      const { currentPage = 1, pageSize = 6 } = params
         if (context.state.columns.currentPage < currentPage) {
          return asyncAndCommit(`/columns?currentPage=${currentPage}&pageSize=${pageSize}`, 'fetchColumns', context.commit)
         }
    },
    fetchColumn({ state, commit }, cid) {
      if (!state.columns.data[cid]) {
        // return getAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
        return asyncAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
      }
    },
    fetchPosts({ state, commit }, cid) {
      if (!state.posts.loadedColumn.includes(cid)) {
      // return getAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit)

        return asyncAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit, { method: 'get' }, cid)
      }

      // cid就是传递过来的currentId
      // const { data } = await axios.get(`/columns/${cid}/posts`)
      // commit('fetchPosts', data)
    },
    fetchPost({ state, commit }, id) {
            // const currentPost = state.posts.data[id]
            // if (!currentPost || !currentPost.content) {
            //    return asyncAndCommit(`/posts/${id}`, 'fetchPost', commit)
            // }
            const currentPost = state.posts.data[id]
            if (!currentPost || !currentPost.content) {
              return asyncAndCommit(`/posts/${id}`, 'fetchPost', commit)
            } else {
                return Promise.resolve({ data: currentPost })
               }
    },
    updatePost({ commit }, { id, payload }) {
      return asyncAndCommit(`/posts/${id}`, 'updatePost', commit, {
        method: 'patch',
        data: payload
      })
    },
    fetchCurrentUser({ commit }) {
      // return asyncAndCommit('/user/current', 'fetchCurrentUser', commit)
      return getAndCommit('/user/current', 'fetchCurrentUser', commit)
    },
    createPosts({ commit }, payload) {
      // return asyncAndCommit('/posts', 'createPosts', commit, { method: 'post', data: payload })
      return postAndCommit('/posts', 'createPosts', commit, payload)
    },
    createPost({ commit }, payload) {
      return asyncAndCommit('/posts', 'createPost', commit, { method: 'post', data: payload })
    },
    login({ commit }, payLoad) {
      // return asyncAndCommit('/user/login', 'login', commit, { method: 'post', data: payLoad })
      return postAndCommit('/user/login', 'login', commit, payLoad)
    },
    getPostIdInfo({ commit }, payload) {
      return asyncAndCommit(`/posts/${payload}`, 'getPostIdInfo', commit)
      // return getAndCommit(`/posts/${payload}`, 'getPostIdInfo', commit)
    },
    deletePost({ commit }, id) {
      return asyncAndCommit(`/posts/${id}`, 'deletePost', commit, {
        method: 'delete'
      })
    },
    // 组合调用
    loginAndFetch({ dispatch }, loginData) {
      // 第一步是登陆
      return dispatch('login', loginData).then((res) => {
        // 第二步是触发action里面的fetchCurrentUser，然后出发commit函数里面的fetchCurrentUser，把user信息放到state.user里面
        return dispatch('fetchCurrentUser')
      })
    }
  },
  getters: {
    getColumns: (state) => {
      return objToArr(state.columns.data)
    },
    getColumnById: (state) => (id: string) => {
      // 找到符合当前用户的
      return state.columns.data[id]// 因为是对象直接获取就可以
    },
    getPostsByCid: (state) => (cid: string) => {
      return objToArr(state.posts.data).filter(item => item.column && item.column === cid)
    },

    getCurrentPost: (state) => (id: string) => {
      return state.posts.data[id]
    }
  }

})

export default store
